package com.oe.monitor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class TPMonitor {

    private static Logger logger = LoggerFactory.getLogger(TPMonitor.class);


    private final   ExecutorService executorService;

    private final   ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;


    private final  static TPMonitor tpMonitor=new TPMonitor();

    private Map<String,TP99Calculator> monitorMap=new ConcurrentHashMap<>();

    private volatile  boolean calculating=false;

    Lock lock = new ReentrantLock();





    private TPMonitor(){
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        scheduledThreadPoolExecutor=new ScheduledThreadPoolExecutor(1);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                calculate();
            }
        },10,10, TimeUnit.SECONDS);
    }

    public static TPMonitor  getTpMonitor(){
        return tpMonitor;
    }

    /**
     * 收集每次服务的响应时间信息
     * @param service
     * @param times
     */
    public void collect(String service,long times){
        /**
         * 异步收集数据
         */
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                //如果正在执行TP99统计，则阻塞等待统计完再收集数据
                if(calculating){
                    synchronized (tpMonitor){
                        try {
                            //logger.warn("========"+Thread.currentThread().getName()+"===========统计TP99开始了，【"+service+"】信息收集暂时阻塞,【"+times+"】。。。。。。=============");
                            tpMonitor.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                doCollect(service,times);

            }
        });
    }

    private void doCollect(String service,long times){
        //logger.warn("========"+Thread.currentThread().getName()+"===========开始收集【"+service+"】:"+times+"=============");
        /**同一服务加锁，避免并发**/
        synchronized (service.intern()){
            TP99Calculator tp99Calculator = monitorMap.get(service);
            if(tp99Calculator==null){//首次请求
                tp99Calculator = new TP99Calculator();
                tp99Calculator.recordTime(times);
                monitorMap.put(service,tp99Calculator);
            }else {
                tp99Calculator.recordTime(times);
            }
        }
    }


    private void calculate() {
                if (!monitorMap.isEmpty()) {
                    setCalculateStatus(true);
                    lock.lock();
                    try {
                        //logger.warn("========"+Thread.currentThread().getName()+"===========开始统计TP99=============");

                        Set<Map.Entry<String, TP99Calculator>> entries = monitorMap.entrySet();
                        for (Map.Entry<String, TP99Calculator> entry : entries) {
                            String key = entry.getKey();
                            TP99Calculator value = entry.getValue();
                           // logger.warn("服务【" + key + "】的TP99性能指标为:" + value.calculateTP99());
                            logger.info("服务【{}】的TP99性能指标为:{}" ,key,value.calculateTP99());
                        }
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        setCalculateStatus(false);
                        //logger.warn("========"+Thread.currentThread().getName()+"===========结束统计TP99=============");


                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        synchronized (tpMonitor){
                            //logger.warn("========"+Thread.currentThread().getName()+"===========开始唤醒等待的收集线程=============");
                            tpMonitor.notifyAll();
                        }
                        lock.unlock();
                    }


                }

    }

    private void setCalculateStatus(boolean status) {
        calculating = status;
    }
}
